import React, {
  forwardRef,
  useEffect,
  useImperativeHandle,
  useMemo,
  useRef,
  useState,
} from 'react';
import styles from './index.less';
import _ from 'lodash';
import { Button, DatePicker, Form, Input, Select, Space } from 'antd';
import { useForm } from 'antd/es/form/Form';
import { TjSelect, TjStation } from '@/pages/ETrade/components';
import moment from 'moment';

const { RangePicker } = DatePicker;

/*
show的用法
如果其中一个条件满足则展示
[{ test1: 1, test4: [1] }]
同时满足时展示
[{ test1: 1 }, { test4: [1] }]
 */

const TjForm = forwardRef(
  (
    {
      onFinish,
      onValuesChange,
      colon = false,
      list = [],
      right = null,
      initialValues = {},
      firstAction = true,
      showBtn = true,
      formProps = {},
    },
    ref,
  ) => {
    const [form] = useForm();

    const [formList, setFormList] = useState([]);

    const [formInitValues, setFormInitValues] = useState({});

    const [btnDisable, setBtnDisable] = useState(false);

    const promiseData = useRef({});

    useEffect(() => {
      (async () => {
        if (initialValues) {
          let value = {};
          list.forEach((i, k) => {
            if (i.name instanceof Array && i.type === 'RangePicker') {
              value[i.name?.toString() + k] = i.name.map((n) => {
                return moment(initialValues[n]);
              });
            } else {
              value[i.name] = initialValues[i.name];
            }
          });
          form.setFieldsValue(value);
          setFormInitValues(value);
          if (list instanceof Array) {
            await changeFormList();
          }
        }
        if (firstAction) {
          form.submit();
        }
      })();
    }, []);

    const getOptionsByDepend = (elData) => {
      let data = {};
      const v = getFinishValue(form.getFieldsValue(true));
      const keys = elData.depend?.keys || [];
      const value = {};
      keys.forEach((k) => {
        value[k] = v[k];
      });
      data = elData.depend?.onChange?.(value);
      if (data instanceof Promise) {
        // 当为Promise时为了不阻塞界面渲染先缓存到ref
        promiseData.current[elData.name] = data;
        setBtnDisable(true);
        return { ...elData, options: [], loading: true };
      } else {
        const { options = [], value } = data;
        form.setFieldsValue({
          [elData.name]: value,
        });
        return { ...elData, options };
      }
    };

    useImperativeHandle(ref, () => ({
      form: form,
    }));

    const getFinishValue = (v = {}) => {
      const value = _.cloneDeep(v ? v : {});
      list.forEach((i, k) => {
        if (i.name instanceof Array && i.type === 'RangePicker') {
          const key = i.name.toString() + k;
          const v = value[key];
          i.name.forEach((n, index) => {
            value[n] = moment(v[index]).format(i.format || 'YYYYMMDD');
          });
          delete value[key];
        }
      });
      return value;
    };

    const onReset = async () => {
      form.setFieldsValue(formInitValues);
      await changeFormList();
    };

    const getPromiseData = async (v) => {
      for (let key in promiseData.current) {
        const { options = [], value } = await promiseData.current[key];
        let arr = v.map((i) => (i.name === key ? { ...i, options, loading: false } : i));
        setFormList(arr);
        form.setFieldsValue({
          [key]: value,
        });
      }
      promiseData.current = {};
      setBtnDisable(false);
    };

    const changeFormList = async () => {
      const values = getFinishValue(form.getFieldsValue(true));
      let arr = list.slice();
      arr = arr.map((i) => {
        return i.depend ? getOptionsByDepend(i) : i;
      });
      arr = arr.filter((i) => {
        if (i.show && _.isArray(i.show)) {
          const result = [];
          i.show.forEach((s) => {
            const objResult = [];
            if (_.isObject(s)) {
              for (let k in s) {
                const v1 = s[k]?.toString();
                const v2 = values[k]?.toString();
                objResult.push(v1 === v2);
              }
            }
            result.push(objResult.some((t) => t));
          });
          if (result.every((t) => t)) {
            return i;
          }
        } else {
          return i;
        }
      });
      setFormList(arr);
      await getPromiseData(arr);
    };

    const formOnValuesChange = async (changedValues, allValues) => {
      await changeFormList();
      onValuesChange?.(changedValues, allValues);
    };

    const formFinish = (value) => {
      onFinish?.(getFinishValue(value));
    };

    const getOption = (arr) => {
      let data = [];
      const recursive = (v) => {
        v.forEach((i) => {
          if (i.children instanceof Array) {
            recursive(i.children);
          } else {
            data.push(i);
          }
        });
      };
      recursive(arr);
      return data;
    };

    const _getElement = (el = { props: {} }) => {
      switch (el.type) {
        case 'Select':
          return (
            <Select
              style={{ width: el.width || 200 }}
              placeholder={'请选择' + el.label}
              loading={!!el.loading}
              onChange={el.onChange}
              {...(el?.props || {})}
            >
              {el.options &&
                el.options.map((i) => (
                  <Select.Option value={i.value} key={i.value}>
                    {i.label}
                  </Select.Option>
                ))}
            </Select>
          );
        case 'DatePicker':
          return (
            <DatePicker
              style={{ width: el.width || 200 }}
              placeholder={'请选择' + el.label}
              onChange={el.onChange}
              {...(el?.props || {})}
            />
          );
        case 'RangePicker':
          return (
            <RangePicker
              format={el.format ? el.format : 'YYYYMMDD'}
              style={{ width: el.width || 260 }}
              onChange={el.onChange}
              {...(el?.props || {})}
            />
          );
        case 'TjSelect':
          return (
            <TjSelect
              style={{ width: el.width || 200 }}
              options={el.options || []}
              mode={'multiple'}
              loading={!!el.loading}
              label={el.label}
              placeholder={'请选择' + el.label}
              onChange={el.onChange}
              {...(el?.props || {})}
            />
          );
        case 'TjStation':
          if (el?.props?.disabled) {
            const arr = getOption(el.options || []);
            return <Select disabled={true} style={{ width: el.width || 200 }} options={arr} />;
          } else {
            return (
              <TjStation
                width={el.width}
                options={el.options || []}
                showSearch
                label={el.label}
                placeholder={'请选择' + el.label}
                onChange={el.onChange}
                {...(el?.props || {})}
              />
            );
          }
        case 'Input':
          return (
            <Input
              style={{ width: el.width || 200 }}
              placeholder={'请输入' + el.label}
              onChange={el.onChange}
              {...(el?.props || {})}
            />
          );
        case 'Other':
          return el.element || null;
      }
    };

    const _getLine = (el, index) => {
      return (
        <Form.Item
          colon={el.colon || false}
          key={el.name?.toString() + index}
          name={el.name instanceof Array ? el.name.toString() + index : el.name}
          label={el.label || ''}
          style={{ margin: '2px 0' }}
          rules={
            el?.required || [
              {
                required: false,
                // message: (el.label || '') + '不能为空',
              },
            ]
          }
        >
          {_getElement(el)}
        </Form.Item>
      );
    };

    return (
      <div className={styles.head}>
        <Form
          className={styles.form}
          form={form}
          labelCol={formProps.labelCol || { span: 5 }}
          wrapperCol={formProps.wrapperCol || { span: 16 }}
          onValuesChange={formOnValuesChange}
          onFinish={formFinish}
        >
          <Space size={16} wrap direction={formProps?.direction || 'horizontal'}>
            {useMemo(() => formList.map((el, index) => _getLine(el, index)), [formList])}
            {showBtn && (
              <>
                <Button
                  type="primary"
                  htmlType="submit"
                  disabled={btnDisable}
                  style={{ height: 32, width: 96 }}
                >
                  查询
                </Button>
                <Button
                  htmlType="button"
                  onClick={onReset}
                  disabled={btnDisable}
                  style={{ height: 32, width: 96 }}
                >
                  重置
                </Button>
              </>
            )}
          </Space>
        </Form>
        <Space size={16} wrap>
          {right}
        </Space>
      </div>
    );
  },
);

export default TjForm;
